﻿package controls 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.text.TextField;
	import flash.ui.Keyboard;
	import flash.utils.Timer;
	
	/**
	 * ...
	 * @author Daniel Sheldon
	 */
	public class NumericSetting extends Sprite
	{
		public var label:TextField;
		public var value:TextField;
		public var up:Sprite;
		public var down:Sprite;
		
		private var settingName:String;
		private var settingHolder:Class;
		private var simpleName:String;
		private var minValue:int;
		private var maxValue:int;
		private var interval:Number;
		private var precision:int;
		
		private var modifier:int;
		private var amount:int = 0;
		private var _settingValue:Number;
		
		private var updateTimer:Timer = new Timer(100);
		
		public function NumericSetting(settingName:String, settingHolder:Class, simpleName:String = null, minValue:int = 0, maxValue:int = 100, interval:Number = 1, precision:int = 1) 
		{
			this.settingName = settingName;
			this.settingHolder = settingHolder;
			this.simpleName = simpleName;
			this.minValue = minValue;
			this.maxValue = maxValue;
			this.interval = interval;
			this.precision = precision;
			
			label.mouseEnabled = false;
			label.text = (simpleName) ? simpleName : settingName;
			
			settingValue = settingHolder[settingName];
			
			value.addEventListener(FocusEvent.FOCUS_OUT, focusOutHandler);
			value.addEventListener(KeyboardEvent.KEY_DOWN, keyHandler);
						
			updateTimer.addEventListener(TimerEvent.TIMER, updateHandler)
			
			up.buttonMode = true;
			down.buttonMode = true;
			
			up.addEventListener(MouseEvent.CLICK, clickHandler);
			down.addEventListener(MouseEvent.CLICK, clickHandler);
			
			up.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			down.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			
			up.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
			down.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
		}
		
		private function mouseDownHandler(e:MouseEvent):void 
		{
			if (e.target == up)
			{
				modifier = 1;
			}else {
				modifier = -1;
			}
			
			updateTimer.start();
		}
		
		private function mouseUpHandler(e:MouseEvent):void 
		{
			updateTimer.reset();
		}
		
		private function clickHandler(e:MouseEvent):void 
		{
			if (updateTimer.currentCount > 0)
			{
				return;
			}
			
			if (e.target == up)
			{
				settingValue += interval;
			}else {
				settingValue -= interval;
			}
			updateSetting();
		}
		
		private function updateHandler(e:TimerEvent):void 
		{
			amount = Math.min(Math.max(updateTimer.currentCount / 3, 1), 5);
			settingValue = settingValue + (modifier * (amount * interval));
			
			stage.focus = null;
			
			updateSetting();
		}
				
		private function keyHandler(e:KeyboardEvent):void 
		{
			if (e.keyCode == Keyboard.ENTER)
			{
				stage.focus = null;
			}
		}
		
		private function focusOutHandler(e:FocusEvent):void 
		{
			settingValue = Number(value.text);
			updateSetting();
		}
		
		private function updateSetting():void
		{
			settingHolder[settingName] = settingValue;
		}
		
		public function get settingValue():Number { return _settingValue; }
		
		public function set settingValue(value:Number):void 
		{
			_settingValue =  Math.max(Math.min(value, maxValue), minValue);
			
			this.value.text = _settingValue.toFixed(precision)
		}
	}
	
}